<?php
/**
 * 积分逻辑层
 * @author 王勇程 <laughskydragon@qq.com>
 */

namespace app\common\logic;

class Points extends LogicBase
{
    /**
     * 获取积分商品搜索条件
     */
    public function getPointsProductWhere($data = [])
    {
        $where = [];
        
        // 商品名称搜索
        !empty($data['search_data']) && $where['name'] = ['like', '%' . $data['search_data'] . '%'];
        
        // 分类筛选
        !empty($data['category']) && $where['category'] = $data['category'];
        
        // 状态筛选
        isset($data['status']) && $data['status'] !== '' && $where['status'] = $data['status'];
        
        // 积分范围筛选
        if (isset($data['min_points']) && $data['min_points'] !== '') {
            $where['points'] = ['>=', $data['min_points']];
        }
        if (isset($data['max_points']) && $data['max_points'] !== '') {
            if (isset($where['points'])) {
                $where['points'] = ['between', [$data['min_points'], $data['max_points']]];
            } else {
                $where['points'] = ['<=', $data['max_points']];
            }
        }
        
        // 库存筛选
        if (isset($data['min_stock']) && $data['min_stock'] !== '') {
            $where['stock'] = ['>=', $data['min_stock']];
        }
        
        // 时间范围搜索
        !empty($data['start_time']) && $where['create_time'] = ['>=', strtotime($data['start_time'])];
        !empty($data['end_time']) && $where['create_time'] = ['<=', strtotime($data['end_time'])];
        
        return $where;
    }

    /**
     * 获取积分记录搜索条件
     */
    public function getPointsRecordWhere($data = [])
    {
        $where = [];
        
        // 用户ID筛选
        !empty($data['user_id']) && $where['user_id'] = $data['user_id'];
        
        // 类型筛选
        !empty($data['type']) && $where['type'] = $data['type'];
        
        // 积分范围筛选
        if (isset($data['min_points']) && $data['min_points'] !== '') {
            $where['points'] = ['>=', $data['min_points']];
        }
        if (isset($data['max_points']) && $data['max_points'] !== '') {
            if (isset($where['points'])) {
                $where['points'] = ['between', [$data['min_points'], $data['max_points']]];
            } else {
                $where['points'] = ['<=', $data['max_points']];
            }
        }
        
        // 描述搜索
        !empty($data['search_data']) && $where['description'] = ['like', '%' . $data['search_data'] . '%'];
        
        // 时间范围搜索
        !empty($data['start_time']) && $where['create_time'] = ['>=', strtotime($data['start_time'])];
        !empty($data['end_time']) && $where['create_time'] = ['<=', strtotime($data['end_time'])];
        
        // 今日数据筛选
        if (!empty($data['create_time']) && is_string($data['create_time'])) {
            $date = $data['create_time'];
            $startTime = strtotime($date . ' 00:00:00');
            $endTime = strtotime($date . ' 23:59:59');
            $where['create_time'] = ['between', [$startTime, $endTime]];
        }
        
        return $where;
    }

    /**
     * 获取签到记录搜索条件
     */
    public function getCheckinRecordWhere($data = [])
    {
        $where = [];
        
        // 用户ID筛选
        !empty($data['user_id']) && $where['user_id'] = $data['user_id'];
        
        // 签到日期筛选
        !empty($data['checkin_date']) && $where['checkin_date'] = $data['checkin_date'];
        
        // 积分范围筛选
        if (isset($data['min_points']) && $data['min_points'] !== '') {
            $where['points'] = ['>=', $data['min_points']];
        }
        if (isset($data['max_points']) && $data['max_points'] !== '') {
            if (isset($where['points'])) {
                $where['points'] = ['between', [$data['min_points'], $data['max_points']]];
            } else {
                $where['points'] = ['<=', $data['max_points']];
            }
        }
        
        // 连续天数筛选
        if (isset($data['min_continuous_days']) && $data['min_continuous_days'] !== '') {
            $where['continuous_days'] = ['>=', $data['min_continuous_days']];
        }
        
        // 时间范围搜索
        !empty($data['start_time']) && $where['create_time'] = ['>=', strtotime($data['start_time'])];
        !empty($data['end_time']) && $where['create_time'] = ['<=', strtotime($data['end_time'])];
        
        // 今日数据筛选
        if (!empty($data['create_time']) && is_string($data['create_time'])) {
            $date = $data['create_time'];
            $startTime = strtotime($date . ' 00:00:00');
            $endTime = strtotime($date . ' 23:59:59');
            $where['create_time'] = ['between', [$startTime, $endTime]];
        }
        
        return $where;
    }
    
    /**
     * 每日签到
     */
    public function dailyCheckin($data = [])
    {
        $userId = $data['user_id'] ?? 0;
        
        if (!$userId) {
            return [RESULT_ERROR, '用户ID不能为空'];
        }
        
        try {
            // 检查用户
            $user = $this->modelUser->getInfo(['id' => $userId]);
            if (!$user) {
                return [RESULT_ERROR, '用户不存在'];
            }
            
            // 检查今日是否已签到
            $today = date('Y-m-d');
            $todayCheckin = $this->modelCheckinRecord->getInfo([
                'user_id' => $userId,
                'checkin_date' => $today
            ]);
            
            if ($todayCheckin) {
                return [RESULT_ERROR, '今日已签到'];
            }
            
            // 获取连续签到天数
            $continuousDays = $this->getContinuousCheckinDays($userId);
            
            // 计算签到奖励积分
            $points = $this->calculateCheckinPoints($continuousDays + 1);
            
            // 创建签到记录
            $checkinData = [
                'user_id' => $userId,
                'checkin_date' => $today,
                'points' => $points,
                'continuous_days' => $continuousDays + 1
                // create_time和update_time由系统自动处理
            ];
            
            $checkinId = $this->modelCheckinRecord->insertGetId($checkinData);
            
            if (!$checkinId) {
                return [RESULT_ERROR, '签到失败'];
            }
            
            // 更新用户积分
            $newPoints = $user['total_points'] + $points;
            $this->modelUser->updateInfo(['id' => $userId], [
                'total_points' => $newPoints
                // update_time由系统自动处理
            ]);
            
            // 记录积分变动
            $this->modelPointsRecord->insertGetId([
                'user_id' => $userId,
                'type' => 'checkin',
                'points' => $points,
                'description' => "每日签到奖励，连续{$checkinData['continuous_days']}天"
                // create_time和update_time由系统自动处理
            ]);
            
            // 发送签到成功消息
            $this->logicMessage->sendSystemMessage(
                $userId,
                '签到成功',
                "签到成功！获得{$points}积分，连续签到{$checkinData['continuous_days']}天。",
                'system',
                json_encode(['points' => $points, 'continuous_days' => $checkinData['continuous_days']])
            );
            
            $data = [
                'points' => $points,
                'continuous_days' => $checkinData['continuous_days'],
                'total_points' => $newPoints
            ];
            
            return $data;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('每日签到失败：' . $e->getMessage());
            return [RESULT_ERROR, '签到失败'];
        }
    }
    
    /**
     * 获取签到状态
     */
    public function getCheckinStatus($data = [])
    {
        $userId = $data['user_id'] ?? 0;
        
        if (!$userId) {
            return [RESULT_ERROR, '用户ID不能为空'];
        }
        try {
            $user = $this->modelUser->getInfo(['id' => $userId]);
            if (!$user) {
                return [RESULT_ERROR, '用户不存在'];
            }
            
            $today = date('Y-m-d');
            $todayCheckin = $this->modelCheckinRecord->getInfo([
                'user_id' => $userId,
                'checkin_date' => $today
            ]);
            
            $isCheckedIn = !empty($todayCheckin);
            $continuousDays = $this->getContinuousCheckinDays($userId);
            $nextPoints = $this->calculateCheckinPoints($continuousDays + 1);
            
            // 获取本月签到记录
            $monthStart = date('Y-m-01');
            $monthEnd = date('Y-m-t');
            $monthCheckins = $this->modelCheckinRecord->getColumn([
                'user_id' => $userId,
                'checkin_date' => ['between', [$monthStart, $monthEnd]]
            ], 'checkin_date');
            
            $data = [
                'is_checked_in' => $isCheckedIn,
                'continuous_days' => $continuousDays,
                'next_points' => $nextPoints,
                'total_points' => $user['total_points'],
                'month_checkins' => $monthCheckins ?: [],
                'checkin_calendar' => $this->getCheckinCalendar($userId)
            ];
            
            return $data;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('获取签到状态失败：' . $e->getMessage());
            return [RESULT_ERROR, '获取签到状态失败'];
        }
    }
    
    /**
     * 获取积分商城商品列表
     */
    public function getPointsMall($data = [])
    {
        $page = $data['page'] ?? 1;
        $limit = $data['limit'] ?? 20;
        $category = $data['category'] ?? '';
        
        try {
            $where = ['status' => 1]; // 上架状态
            
            if ($category) {
                $where['category'] = $category;
            }
            
            $list = $this->modelPointsProduct->getList(
                $where,
                true,
                'sort desc, id desc',
                ['list_rows' => $limit, 'page' => $page]
            );
            
            // 格式化数据
            if (!empty($list)) {
                foreach ($list as $key => $item) {
                    $item['create_time_text'] = date('Y-m-d H:i:s', $item['create_time']);
                    
                    // 解析图片
                    if ($item['images']) {
                        $item['images'] = json_decode($item['images'], true);
                    }
                    
                    // 重新赋值修改后的数据
                    $list[$key] = $item;
                }
            }
            
            return $list;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('获取积分商城失败：' . $e->getMessage());
            return [RESULT_ERROR, '获取积分商城失败'];
        }
    }
    
    /**
     * 兑换积分商品
     */
    public function exchangeProduct($data = [])
    {
        $userId = $data['user_id'] ?? 0;
        $productId = $data['product_id'] ?? 0;
        $quantity = $data['quantity'] ?? 1;
        
        if (!$userId) {
            return [RESULT_ERROR, '用户ID不能为空'];
        }
        if (!$productId) {
            return [RESULT_ERROR, '商品ID不能为空'];
        }
        
        try {
            // 检查用户
            $user = $this->modelUser->getInfo(['id' => $userId]);
            if (!$user) {
                return [RESULT_ERROR, '用户不存在'];
            }
            
            // 检查商品
            $product = $this->modelPointsProduct->getInfo(['id' => $productId, 'status' => 1]);
            if (!$product) {
                return [RESULT_ERROR, '商品不存在或已下架'];
            }
            
            // 检查库存
            if ($product['stock'] < $quantity) {
                return [RESULT_ERROR, '库存不足'];
            }
            
            // 计算所需积分
            $totalPoints = $product['points'] * $quantity;
            
            // 检查用户积分
            if ($user['total_points'] < $totalPoints) {
                return [RESULT_ERROR, '积分不足'];
            }
            
            // 生成兑换订单号
            $exchangeNo = 'EX' . date('YmdHis') . rand(1000, 9999);
            
            // 扣减用户积分
            $newPoints = $user['total_points'] - $totalPoints;
            $this->modelUser->updateInfo(['id' => $userId], [
                'total_points' => $newPoints,
                'update_time' => time()
            ]);
            
            // 扣减商品库存
            $this->modelPointsProduct->updateInfo(['id' => $productId], [
                'stock' => $product['stock'] - $quantity,
                'exchange_count' => $product['exchange_count'] + $quantity,
                'update_time' => time()
            ]);
            
            // 记录积分变动
            $this->modelPointsRecord->insertGetId([
                'user_id' => $userId,
                'type' => 'exchange',
                'points' => -$totalPoints,
                'description' => "兑换商品：{$product['name']} x{$quantity}",
                'extra_data' => json_encode([
                    'product_id' => $productId,
                    'product_name' => $product['name'],
                    'quantity' => $quantity,
                    'exchange_no' => $exchangeNo
                ]),
                'create_time' => time(),
                'update_time' => time()
            ]);
            
            // 发送兑换成功消息
            $this->logicMessage->sendSystemMessage(
                $userId,
                '兑换成功',
                "您成功兑换了{$product['name']} x{$quantity}，消耗{$totalPoints}积分。",
                'system',
                json_encode([
                    'exchange_no' => $exchangeNo,
                    'product_name' => $product['name'],
                    'quantity' => $quantity,
                    'points' => $totalPoints
                ])
            );
            
            $data = [
                'exchange_no' => $exchangeNo,
                'product_name' => $product['name'],
                'quantity' => $quantity,
                'points_used' => $totalPoints,
                'remaining_points' => $newPoints
            ];
            
            return $data;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('兑换积分商品失败：' . $e->getMessage());
            return [RESULT_ERROR, '兑换失败'];
        }
    }
    
    /**
     * 获取积分记录
     */
    public function getPointsRecords($data = [])
    {
        $userId = $data['user_id'] ?? 0;
        $type = $data['type'] ?? '';
        $page = $data['page'] ?? 1;
        $limit = $data['limit'] ?? 20;
        
        if (!$userId) {
            return [RESULT_ERROR, '用户ID不能为空'];
        }
        
        try {
            $where = ['user_id' => $userId];
            
            if ($type) {
                $where['type'] = $type;
            }
            
            $list = $this->modelPointsRecord->getList(
                $where,
                true,
                'id desc',
                ['list_rows' => $limit, 'page' => $page]
            );
            
            // 格式化数据
            if (!empty($list)) {
                foreach ($list as $key => $item) {
                    $item['create_time_text'] = date('Y-m-d H:i:s', $item['create_time']);
                    $item['type_text'] = $this->getPointsTypeText($item['type']);
                    $item['points_text'] = $item['points'] > 0 ? '+' . $item['points'] : $item['points'];
                    
                    // 解析额外数据
                    if ($item['extra_data']) {
                        $item['extra_data'] = json_decode($item['extra_data'], true);
                    }
                    
                    // 重新赋值修改后的数据
                    $list[$key] = $item;
                }
            }
            
            return $list;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('获取积分记录失败：' . $e->getMessage());
            return [RESULT_ERROR, '获取积分记录失败'];
        }
    }
    
    /**
     * 获取用户积分信息
     */
    public function getUserPointsInfo($data = [])
    {
        $userId = $data['user_id'] ?? 0;
        
        if (!$userId) {
            return [RESULT_ERROR, '用户ID不能为空'];
        }
        
        try {
            $user = $this->modelUser->getInfo(['id' => $userId]);
            if (!$user) {
                return [RESULT_ERROR, '用户不存在'];
            }
            
            // 获取今日获得积分
            $todayStart = strtotime(date('Y-m-d'));
            $todayEnd = $todayStart + 86400 - 1;
            $todayPoints = $this->modelPointsRecord->getValue([
                'user_id' => $userId,
                'points' => ['>', 0],
                'create_time' => ['between', [$todayStart, $todayEnd]]
            ], 'SUM(points)') ?: 0;
            
            // 获取本月获得积分
            $monthStart = strtotime(date('Y-m-01'));
            $monthEnd = strtotime(date('Y-m-t')) + 86400 - 1;
            $monthPoints = $this->modelPointsRecord->getValue([
                'user_id' => $userId,
                'points' => ['>', 0],
                'create_time' => ['between', [$monthStart, $monthEnd]]
            ], 'SUM(points)') ?: 0;
            
            // 获取连续签到天数
            $continuousDays = $this->getContinuousCheckinDays($userId);
            
            // 检查今日是否已签到
            $today = date('Y-m-d');
            $todayCheckin = $this->modelCheckinRecord->getInfo([
                'user_id' => $userId,
                'checkin_date' => $today
            ]);
            
            $data = [
                'total_points' => $user['total_points'],
                'today_points' => $todayPoints,
                'month_points' => $monthPoints,
                'continuous_checkin_days' => $continuousDays,
                'is_checked_in_today' => !empty($todayCheckin),
                'next_checkin_points' => $this->calculateCheckinPoints($continuousDays + 1)
            ];
            
            return $data;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('获取用户积分信息失败：' . $e->getMessage());
            return [RESULT_ERROR, '获取用户积分信息失败'];
        }
    }
    
    /**
     * 获取积分商品详情
     */
    public function getProductDetail($data = [])
    {
        $productId = $data['product_id'] ?? 0;
        
        if (!$productId) {
            return [RESULT_ERROR, '商品ID不能为空'];
        }
        
        try {
            $product = $this->modelPointsProduct->getInfo(['id' => $productId]);
            if (!$product) {
                return [RESULT_ERROR, '商品不存在'];
            }
            
            // 格式化数据
            $product['create_time_text'] = date('Y-m-d H:i:s', $product['create_time']);
            
            // 解析图片
            if ($product['images']) {
                $product['images'] = json_decode($product['images'], true);
            }
            
            return $product;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('获取积分商品详情失败：' . $e->getMessage());
            return [RESULT_ERROR, '获取商品详情失败'];
        }
    }
    
    /**
     * 获取兑换记录
     */
    public function getExchangeRecords($data = [])
    {
        $userId = $data['user_id'] ?? 0;
        $page = $data['page'] ?? 1;
        $limit = $data['limit'] ?? 20;
        
        if (!$userId) {
            return [RESULT_ERROR, '用户ID不能为空'];
        }
        
        try {
            $where = ['user_id' => $userId, 'type' => 'exchange'];
            
            $list = $this->modelPointsRecord->getList(
                $where,
                true,
                'id desc',
                ['list_rows' => $limit, 'page' => $page]
            );
            
            // 格式化数据
            if (!empty($list)) {
                foreach ($list as $key => $item) {
                    $item['create_time_text'] = date('Y-m-d H:i:s', $item['create_time']);
                    $item['points_text'] = abs($item['points']);
                    
                    // 解析额外数据
                    if ($item['extra_data']) {
                        $item['extra_data'] = json_decode($item['extra_data'], true);
                    }
                    
                    // 重新赋值修改后的数据
                    $list[$key] = $item;
                }
            }
            
            return $list;
            
        } catch (\Exception $e) {
            \think\facade\Log::error('获取兑换记录失败：' . $e->getMessage());
            return [RESULT_ERROR, '获取兑换记录失败'];
        }
    }
    
    /**
     * 添加积分
     */
    public function addPoints($userId, $points, $type, $description, $extraData = '')
    {
        try {
            if ($points <= 0) {
                return [RESULT_ERROR, '积分数量必须大于0'];
            }
            
            $user = $this->modelUser->getInfo(['id' => $userId]);
            if (!$user) {
                return [RESULT_ERROR, '用户不存在'];
            }
            
            // 更新用户积分
            $newPoints = $user['total_points'] + $points;
            $this->modelUser->updateInfo(['id' => $userId], [
                'total_points' => $newPoints,
                'update_time' => time()
            ]);
            
            // 记录积分变动
            $this->modelPointsRecord->insertGetId([
                'user_id' => $userId,
                'type' => $type,
                'points' => $points,
                'description' => $description,
                'extra_data' => $extraData,
                'create_time' => time(),
                'update_time' => time()
            ]);
            
            return ['new_points' => $newPoints];
            
        } catch (\Exception $e) {
            \think\facade\Log::error('添加积分失败：' . $e->getMessage());
            return [RESULT_ERROR, '添加积分失败'];
        }
    }
    
    /**
     * 获取连续签到天数
     */
    private function getContinuousCheckinDays($userId)
    {
        $continuousDays = 0;
        $currentDate = date('Y-m-d');
        
        for ($i = 1; $i <= 365; $i++) {
            $checkDate = date('Y-m-d', strtotime("-{$i} day"));
            $checkin = $this->modelCheckinRecord->getInfo([
                'user_id' => $userId,
                'checkin_date' => $checkDate
            ]);
            
            if ($checkin) {
                $continuousDays++;
            } else {
                break;
            }
        }
        
        return $continuousDays;
    }
    
    /**
     * 计算签到奖励积分
     */
    private function calculateCheckinPoints($continuousDays)
    {
        // 基础积分
        $basePoints = 10;
        
        // 连续签到奖励
        if ($continuousDays >= 30) {
            return $basePoints + 50; // 连续30天额外50积分
        } elseif ($continuousDays >= 15) {
            return $basePoints + 30; // 连续15天额外30积分
        } elseif ($continuousDays >= 7) {
            return $basePoints + 20; // 连续7天额外20积分
        } elseif ($continuousDays >= 3) {
            return $basePoints + 10; // 连续3天额外10积分
        }
        
        return $basePoints;
    }
    
    /**
     * 获取签到日历
     */
    private function getCheckinCalendar($userId)
    {
        $monthStart = date('Y-m-01');
        $monthEnd = date('Y-m-t');
        
        $checkins = $this->modelCheckinRecord->getList([
            'user_id' => $userId,
            'checkin_date' => ['between', [$monthStart, $monthEnd]]
        ], 'checkin_date,points,continuous_days', 'checkin_date asc');
        
        $calendar = [];
        if (!empty($checkins)) {
            foreach ($checkins as $checkin) {
                $calendar[$checkin['checkin_date']] = [
                    'points' => $checkin['points'],
                    'continuous_days' => $checkin['continuous_days']
                ];
            }
        }
        
        return $calendar;
    }
    
    /**
     * 获取积分类型文本
     */
    private function getPointsTypeText($type)
    {
        $typeMap = [
            'checkin' => '签到奖励',
            'register' => '注册奖励',
            'invite' => '邀请奖励',
            'exchange' => '商品兑换',
            'system' => '系统奖励'
        ];
        
        return $typeMap[$type] ?? '未知类型';
    }
    
    /**
     * 获取积分记录搜索条件
     */
    public function getWhere($data = [])
    {
        $where = [];
        
        // 用户ID筛选
        !empty($data['user_id']) && $where['user_id'] = $data['user_id'];
        
        // 积分类型筛选
        !empty($data['type']) && $where['type'] = $data['type'];
        
        // 积分范围筛选
        if (isset($data['min_points']) && $data['min_points'] !== '') {
            $where['points'] = ['>=', $data['min_points']];
        }
        if (isset($data['max_points']) && $data['max_points'] !== '') {
            if (isset($where['points'])) {
                $where['points'] = ['between', [$data['min_points'], $data['max_points']]];
            } else {
                $where['points'] = ['<=', $data['max_points']];
            }
        }
        
        // 时间范围筛选
        !empty($data['start_time']) && $where['create_time'] = ['>=', strtotime($data['start_time'])];
        !empty($data['end_time']) && $where['create_time'] = ['<=', strtotime($data['end_time'])];
        
        // 搜索条件：描述
        !empty($data['search_data']) && $where['description'] = ['like', '%'.$data['search_data'].'%'];
        
        return $where;
    }
    
    /**
     * 获取积分记录列表
     */
    public function getPointsList($where = [], $field = true, $order = 'create_time desc', $paginate = DB_LIST_ROWS)
    {
        // 排除已删除的记录
        $where[DATA_STATUS_NAME] = ['neq', DATA_DELETE];
        
        return $this->modelPointsRecord->getList($where, $field, $order, $paginate);
    }
    
    /**
     * 积分调整
     */
    public function pointsAdjust($data = [])
    {
        $userId = $data['user_id'] ?? 0;
        $points = $data['points'] ?? 0;
        $type = $data['type'] ?? 'admin_adjust'; // add 或 subtract
        $description = $data['description'] ?? '管理员调整';
        
        if (!$userId) {
            return [RESULT_ERROR, '用户ID不能为空'];
        }
        
        if (!$points) {
            return [RESULT_ERROR, '积分数量不能为空'];
        }
        
        try {
            $user = $this->modelUser->getInfo(['id' => $userId]);
            if (!$user) {
            return [RESULT_ERROR, '用户不存在'];
        }
            
            $newPoints = $user['total_points'] + $points;
            $newPoints = max(0, $newPoints); // 积分不能为负数
            
            // 更新用户积分
            $result = $this->modelUser->updateInfo(['id' => $userId], [
                'total_points' => $newPoints,
                'update_time' => time()
            ]);
            
            if ($result) {
                // 记录积分变动
                $this->modelPointsRecord->insertGetId([
                    'user_id' => $userId,
                    'type' => $type,
                    'points' => $points,
                    'description' => $description,
                    'create_time' => time(),
                    'update_time' => time()
                ]);
                
                action_log('积分调整', '用户积分调整，user_id：' . $userId . '，积分：' . $points);
            }
            
            return $result ? [RESULT_SUCCESS, '积分调整成功'] : [RESULT_ERROR, '积分调整失败'];
            
        } catch (\Exception $e) {
            \think\facade\Log::error('积分调整失败：' . $e->getMessage());
            return [RESULT_ERROR, '积分调整失败'];
        }
    }
}